﻿using System;
using System.Collections;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Client.planet;
using Client.star;

namespace Client
{
    /// <summary>
    /// Interaction logic for StarMap.xaml
    /// </summary>
    public partial class StarMap : UserControl
    {
        #region P/Invoke
        [StructLayout(LayoutKind.Sequential)]
        struct MyPoint
        {
            public int x;
            public int y;
        }
        [DllImport("user32")]
        private static extern bool GetCursorPos(out MyPoint LPPoint); 
        #endregion

        #region Declares
        int rows, cols, seed;
        double cxInitialMap = 900, cyInitialMap = 700;

        Star[,] starArray;
        Random random;
        #endregion

        public StarMap()
        {
            InitializeComponent();

            Connect();

            transformGroup = new TransformGroup();
            transformGroup.Children.Add(scaleTransform);
            transformGroup.Children.Add(transFinal);
            canvas1.RenderTransform = transformGroup;
            
            Init();

            GetSeed();
            random = new Random(seed);

            CreateStarMap();
        }
        /// <summary>
        /// Registers TcpChannel and saves channel and remoted object references locally
        /// </summary>
        private void Connect()
        {
            TcpChannel tcpChannel1 = new TcpChannel();
            TcpChannel1 = tcpChannel1;
            ChannelServices.RegisterChannel(tcpChannel1, true);
            RemoteGame.Game game = (RemoteGame.Game)Activator.GetObject(typeof(RemoteGame.Game), "tcp://localhost:9999/Game");
            Game = game;
        }
        /// <summary>
        /// Unregisters TcpChannel
        /// </summary>
        private void Disconnect()
        {
            ChannelServices.UnregisterChannel(TcpChannel1);
            // Used to reset seed instead of reseting remoted game object
            Game.SetSeed();
        }

        /// <summary>
        /// Allocate rows, cols according to user choice.
        /// </summary>
        void Init()
        {
            switch ((string)StartGameOptionsGlobals.GalaxySize)
            {
                case "Small":
                    rows = cols = 4;
                    break;
                case "Medium":
                    rows = cols = 6;
                    break;
                case "Large":
                    rows = cols = 8;
                    break;
                case "Huge":
                    rows = cols = 10;
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Initializes StarNames and StarProduction for the first time right after StarMap initialization
        /// </summary>
        public void ReferencePassed()
        {
            for (int i = 0; i < rows; i++)
                for (int j = 0; j < cols; j++)
                {
                    // Displays(or not) StarName and StarProduction
                    starArray[i, j].Location = new Point(Canvas.GetLeft(starArray[i, j]), Canvas.GetTop(starArray[i, j]));
                }
        }

        /// <summary>
        /// Ger seed from remoted object.
        /// </summary>
        void GetSeed()
        { 
            if (Game == null)
            {
                MessageBox.Show("Could not locate server");
            }
            else
            {
                seed = Game.Seed;
            }
        }

        /// <summary>
        /// Makes stars and centers them. Makes their planets.
        /// </summary>
        void CreateStarMap()
        {
            #region Declares
            ArrayList starNames = new ArrayList();

            Point[,] starPoints = new Point[rows, cols];
            Point[,] starPointsCentered = new Point[rows, cols];

            starArray = new Star[rows, cols];
            #endregion

            starPoints = InitStarPoints(rows, cols);
            InitStarNames(starNames);

            for (int i = 0; i < rows; i++)
                for (int j = 0; j < cols; j++)
                {
                    starArray[i, j] = new Star();
                    starArray[i, j] = MakeStar(starArray[i, j], starNames);
                    starArray[i, j].PlanetArray = MakePlanets(starArray[i, j].StringStarName);
                    starArray[i, j].IsMade = true; // Triggers ToolTip initialization.
                    starPointsCentered[i, j] = SetFromCenter(starPoints[i, j], starArray[i,j]);
                    Canvas.SetLeft(starArray[i, j], starPointsCentered[i, j].X);
                    Canvas.SetTop(starArray[i, j], starPointsCentered[i, j].Y);
                    canvas1.Children.Add(starArray[i, j]);  
                }
        }

        /// <summary>
        /// Assigns a star name. Removes it from starNames so it doesn't repeat.
        /// </summary>
        string AssignStarName(ArrayList starNames)
        {
            int randomIndex = random.Next(starNames.Count);
            string starName = starNames[randomIndex].ToString();
            starNames.RemoveAt(randomIndex);
            return starName;
        }

        /// <summary>
        /// Initializes an ArrayList of names for the stars.
        /// </summary>
        void InitStarNames(ArrayList starNames)
        {
            string path = @"C:\Documents and Settings\Wolf\My Documents\Visual Studio 2008\Projects\MyMoO_Resources\starnames.txt";

            try 
            {
                using (StreamReader sr = new StreamReader(path)) 
                {
                    String line;
                    while ((line = sr.ReadLine()) != null) 
                    {
                        starNames.Add(line);
                    }
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        /// <summary>
        /// Initializes the star's planets and determines their features.
        /// </summary>
        Planet[] MakePlanets(string starName)
        {
            int numberOfPlanets = random.Next(6);
            Planet[] planetArray = new Planet[numberOfPlanets];
            
            // Make planets
            for (int i = 0; i < numberOfPlanets; i++)
            {
                planetArray[i] = new Planet();
                planetArray[i].PlanetType = (PlanetType)random.Next(9); // @PlanetType enum@
                planetArray[i].PlanetSize = (PlanetSize)random.Next(5); // @PlanetSize enum@
                planetArray[i].PlanetWorth = (PlanetWorth)random.Next(5); // @PlanetWorth enum@
                planetArray[i].ImageSource =  new BitmapImage(new Uri(@"C:\Documents and Settings\Wolf\My Documents\Visual Studio 2008\Projects\MyMoO_Resources\planets\"
                    + planetArray[i].PlanetType.ToString() + "0" + random.Next(1, 4).ToString() + ".png"));

                // Make moons
                int numberOfMoons = random.Next((int)planetArray[i].PlanetSize + 2); // + 1 for random exclusive upper limit
                Planet[] moonArray = new Planet[numberOfMoons];

                for (int j = 0; j < numberOfMoons; j++)
                {
                    moonArray[j] = new Planet();
                    moonArray[j].PlanetType = (PlanetType)random.Next(9); // @PlanetType enum@
                    moonArray[j].PlanetSize = (PlanetSize)random.Next((int)planetArray[i].PlanetSize + 1);
                    moonArray[j].PlanetWorth = (PlanetWorth)random.Next(5); // @PlanetWorth enum@
                    moonArray[j].ImageSource = new BitmapImage(new Uri(@"C:\Documents and Settings\Wolf\My Documents\Visual Studio 2008\Projects\MyMoO_Resources\planets\"
                        + moonArray[j].PlanetType.ToString() + "0" + random.Next(1, 4).ToString() + ".png"));

                }

                #region Determine moon indexes
                int moonRoll;
                switch (numberOfMoons) // @PlanetIndex enum@
                {
                    case 1:
                        moonArray[0].PlanetIndex = PlanetIndex.I;
                        break;
                    case 2:
                        moonArray[0].PlanetIndex = (PlanetIndex)random.Next(2);
                        do
                        {
                            moonRoll = random.Next(2);
                            moonArray[1].PlanetIndex = (PlanetIndex)moonRoll;
                        } while (moonRoll == (int)moonArray[0].PlanetIndex);
                        break;
                    case 3:
                        moonArray[0].PlanetIndex = (PlanetIndex)random.Next(3);
                        do
                        {
                            moonRoll = random.Next(3);
                            moonArray[1].PlanetIndex = (PlanetIndex)moonRoll;
                        } while (moonRoll == (int)moonArray[0].PlanetIndex);
                        do
                        {
                            moonRoll = random.Next(3);
                            moonArray[2].PlanetIndex = (PlanetIndex)moonRoll;
                        } while (moonRoll == (int)moonArray[0].PlanetIndex ||
                            moonRoll == (int)moonArray[1].PlanetIndex);
                        break;
                    case 4:
                        moonArray[0].PlanetIndex = (PlanetIndex)random.Next(4);
                        do
                        {
                            moonRoll = random.Next(4);
                            moonArray[1].PlanetIndex = (PlanetIndex)moonRoll;
                        } while (moonRoll == (int)moonArray[0].PlanetIndex);
                        do
                        {
                            moonRoll = random.Next(4);
                            moonArray[2].PlanetIndex = (PlanetIndex)moonRoll;
                        } while (moonRoll == (int)moonArray[0].PlanetIndex ||
                            moonRoll == (int)moonArray[1].PlanetIndex);
                        do
                        {
                            moonRoll = random.Next(4);
                            moonArray[3].PlanetIndex = (PlanetIndex)moonRoll;
                        } while (moonRoll == (int)moonArray[0].PlanetIndex ||
                            moonRoll == (int)moonArray[1].PlanetIndex ||
                            moonRoll == (int)moonArray[2].PlanetIndex);
                        break;
                    case 5:
                        for (int j = 0; j < numberOfMoons; j++)
                        {
                            moonArray[j].PlanetIndex = (PlanetIndex)j;
                        }
                        break;
                    default:
                        break;
                }

                // Determine moon names
                for (int j = 0; j < numberOfMoons; j++)
                {
                    moonArray[j].PlanetName = starName + " " + planetArray[i].PlanetIndex.ToString() + "'s Moon " + moonArray[j].PlanetIndex.ToString();
                }
                #endregion

                planetArray[i].MoonArray = moonArray;
            }

            #region Determine planet indexes
            int planetRoll;
            switch (numberOfPlanets) // @PlanetIndex enum@
            {
                case 1:
                    planetArray[0].PlanetIndex = (PlanetIndex)random.Next(5);
                    break;
                case 2:
                    planetArray[0].PlanetIndex = (PlanetIndex)random.Next(5);
                    do
                    {
                        planetRoll = random.Next(5);
                        planetArray[1].PlanetIndex = (PlanetIndex)planetRoll;
                    } while (planetRoll == (int)planetArray[0].PlanetIndex);
                    break;
                case 3:
                    planetArray[0].PlanetIndex = (PlanetIndex)random.Next(5);
                    do
                    {
                        planetRoll = random.Next(5);
                        planetArray[1].PlanetIndex = (PlanetIndex)planetRoll;
                    } while (planetRoll == (int)planetArray[0].PlanetIndex);
                    do
                    {
                        planetRoll = random.Next(5);
                        planetArray[2].PlanetIndex = (PlanetIndex)planetRoll;
                    } while (planetRoll == (int)planetArray[0].PlanetIndex ||
                        planetRoll == (int)planetArray[1].PlanetIndex);
                    break;
                case 4:
                    planetArray[0].PlanetIndex = (PlanetIndex)(random.Next(5));
                    do
                    {
                        planetRoll = random.Next(5);
                        planetArray[1].PlanetIndex = (PlanetIndex)planetRoll;
                    } while (planetRoll == (int)planetArray[0].PlanetIndex);
                    do
                    {
                        planetRoll = random.Next(5);
                        planetArray[2].PlanetIndex = (PlanetIndex)planetRoll;
                    } while (planetRoll == (int)planetArray[0].PlanetIndex ||
                        planetRoll == (int)planetArray[1].PlanetIndex);
                    do
                    {
                        planetRoll = random.Next(5);
                        planetArray[3].PlanetIndex = (PlanetIndex)planetRoll;
                    } while (planetRoll == (int)planetArray[0].PlanetIndex ||
                        planetRoll == (int)planetArray[1].PlanetIndex ||
                        planetRoll == (int)planetArray[2].PlanetIndex);
                    break;
                case 5:
                    for (int i = 0; i < numberOfPlanets; i++)
                    {
                        planetArray[i].PlanetIndex = (PlanetIndex)i;
                    }
                    break;
                default:
                    break;
            } 
            #endregion

            // Determine planet names
            for (int i = 0; i < numberOfPlanets; i++)
            {
                planetArray[i].PlanetName = starName + " " + planetArray[i].PlanetIndex.ToString();
            }

            return planetArray;
        }

        /// <summary>
        /// Initializes an array of positions for the stars.
        /// </summary>
        Point[,] InitStarPoints(int rows, int cols)
        {
            #region Declares
            Point point = new Point();
            Point[,] starPoints = new Point[rows, cols]; 
            #endregion

            for (int i = 0; i < rows; i++)
                for (int j = 0; j < cols; j++)
                {
                    // Determine numeric range(20% - 80%) of the generic control square for the control grid
                    int randomX = random.Next((int)Math.Round((cxInitialMap / cols) / 5, MidpointRounding.AwayFromZero),
                        ((int)Math.Round(((cxInitialMap / cols) * 80) / 100, MidpointRounding.AwayFromZero))+ 1);
                    int randomY = random.Next((int)Math.Round((cyInitialMap / rows) / 5, MidpointRounding.AwayFromZero),
                        ((int)Math.Round(((cyInitialMap / rows) * 80) / 100, MidpointRounding.AwayFromZero))+ 1); // + 1 for exclusive random upper limit

                    // Set the determined generic control square on the control grid
                    point.X = randomX + i * (int)Math.Round((cxInitialMap / cols), MidpointRounding.AwayFromZero);
                    point.Y = randomY + j * (int)Math.Round((cyInitialMap / rows), MidpointRounding.AwayFromZero);
                    starPoints[i, j] = point;
                }

            return starPoints;
        }

        /// <summary>
        /// Offsets the starting point of a star so it appears like the center point is the Location point.
        /// </summary>
        Point SetFromCenter(Point starPoint, Star star)
        {
            starPoint.X -= star.ActualWidth / 2;
            starPoint.Y -= star.ActualHeight / 2;

            return starPoint;
        }

        /// <summary>
        /// Initialize star and etermine its features.
        /// </summary>
        Star MakeStar(Star star, ArrayList starNames)
        {
            #region Determine StarClass
            int classRoll = random.Next(2, 7); // Roll for five main types of star
            if (classRoll != 2)
                star.StarClass = Client.star.MakeStar.starClass[classRoll];
            else
            {
                int subRoll = random.Next(100);
                if (subRoll < 40) // 40% chance for A type
                    star.StarClass = Client.star.MakeStar.starClass[2];
                else if (subRoll < 70) // 30% chance for B type
                    star.StarClass = Client.star.MakeStar.starClass[1];
                else // 20% chance for O type
                    star.StarClass = Client.star.MakeStar.starClass[0];
            }
            #endregion

            #region Determine LuminosityClass
            int lumRoll = random.Next(3, classRoll * 3); // Each luminosity class has three subclasses, + 1 for exclusive random upper limit
            if (classRoll != 2)
                star.LuminosityClass = Client.star.MakeStar.luminosityClass[lumRoll];
            else
            {
                if (star.StarClass.StarType == StarType.O)
                {
                    lumRoll = 0;
                    star.LuminosityClass = Client.star.MakeStar.luminosityClass[lumRoll];
                }
                else if (star.StarClass.StarType == StarType.B)
                {
                    lumRoll = random.Next(1, 3);
                    star.LuminosityClass = Client.star.MakeStar.luminosityClass[lumRoll];
                }
                else
                {
                    lumRoll = random.Next(1, 4);
                    star.LuminosityClass = Client.star.MakeStar.luminosityClass[lumRoll];
                }
            }
            #endregion

            #region Determine Mass
            double massRoll = random.Next(Convert.ToInt32(Client.star.MakeStar.minMaxMass[(int)star.StarClass.StarType].Min * 100),
                Convert.ToInt32(Client.star.MakeStar.minMaxMass[(int)star.StarClass.StarType].Max * 100 + 1)); // + 1 for exclusive upper random limit
            massRoll /= 100;
            star.Mass = massRoll;
            #endregion

            #region Determine Age
            int ageRoll = random.Next(4); // 4 age zones, 4th zone is checked for atMainSeqLifePeriodEnd
            star.StarAge = (StarAge)ageRoll;
            if (ageRoll == 3)
            {
                int subRoll = random.Next(100); // % chance star is at the end of its main sequence period
                int subHit = random.Next(100); // Roll to hit that chance
                if (subHit <= subRoll) // If chance hit
                {
                    star.StarAge = StarAge.atMainSeqLifePeriodEnd;
                    if (star.LuminosityClass.LuminosityType != LuminosityType.Ia0)
                    {
                        if (star.Mass <= 1.5F)
                        {
                            StarClass starClass = new StarClass(star.StarClass.StarType, StarColor.redGiant);
                            star.StarClass = starClass;
                        }
                        else
                        {
                            StarClass starClass = new StarClass(star.StarClass.StarType, StarColor.redSuperGiant);
                            star.StarClass = starClass;
                        }
                    }
                }
            }

            #endregion

            star.Subtype = random.Next(9);

            #region Determine Size
            // All terms of the formula must be bigger than 0 thus some are offset by 1
            int sizeStarType = (int)star.StarClass.StarType;
            sizeStarType = Math.Abs(sizeStarType - 7); // Reverse index order of StarType enum
            int sizeStarAge = (int)star.StarAge;
            sizeStarAge++;
            int sizeSubtype = star.Subtype;
            sizeSubtype++;
            star.Size = 2 + sizeStarType * 3 + sizeStarAge * 2 + sizeSubtype;
            #endregion

            #region Assign star picture
            int starPictureNumber;
            if (star.AtMainSeqLifePeriodEnd)
                starPictureNumber = random.Next(1, 10);
            else
                starPictureNumber = random.Next(1, 3);
            star.ImageSource = new BitmapImage(new Uri(@"C:\Documents and Settings\Wolf\My Documents\Visual Studio 2008\Projects\MyMoO_Resources\stars\"
                + star.StarClass.StarColor.ToString() + starPictureNumber.ToString() + @".png"));
            #endregion

            star.StringStarName = AssignStarName(starNames);

            return star;
        }

        #region Events
        #region Pan tool #2(backup)
        //private bool isMoving;
        //MyPoint myPointPrev;

        //private void canvas1_MouseDown(object sender, MouseButtonEventArgs e)
        //{
        //    isMoving = e.LeftButton == MouseButtonState.Pressed;
        //    // Previous mouse position.
        //    GetCursorPos(out myPointPrev);
        //}
        //private void canvas1_MouseMove(object sender, MouseEventArgs e)
        //{
        //    if (isMoving)
        //    {
        //        // This mouse position.
        //        MyPoint myPointThis;
        //        GetCursorPos(out myPointThis);
        //        // This mouse position. - Previous mouse position. = offset
        //        Vector offset = new Vector(myPointThis.x - myPointPrev.x, myPointThis.y - myPointPrev.y);
        //        // Location + offset = Location (precheck)
        //        Point loc = new Point(canvas1.Margin.Left + offset.X, canvas1.Margin.Top + offset.Y);

        //        if (canvas1.ActualWidth >= ActualWidth && canvas1.ActualHeight >= ActualHeight)
        //        {
        //            if (loc.X > 0) loc.X = 0;
        //            if (loc.X + canvas1.ActualWidth < ActualWidth) loc.X = ActualWidth - canvas1.ActualWidth;
        //            if (loc.Y > 0) loc.Y = 0;
        //            if (loc.Y + canvas1.ActualHeight < ActualHeight) loc.Y = ActualHeight - canvas1.ActualHeight;
        //        }
        //        else if (canvas1.ActualHeight >= ActualHeight)
        //        {
        //            if (loc.X < 0) loc.X = 0;
        //            if (loc.X + canvas1.ActualWidth > ActualWidth) loc.X = ActualWidth - canvas1.ActualWidth;
        //            if (loc.Y > 0) loc.Y = 0;
        //            if (loc.Y + canvas1.ActualHeight < ActualHeight) loc.Y = ActualHeight - canvas1.ActualHeight;
        //        }
        //        else
        //        {
        //            if (loc.X < 0) loc.X = 0;
        //            if (loc.X + canvas1.ActualWidth > ActualWidth) loc.X = ActualWidth - canvas1.ActualWidth;
        //            if (loc.Y < 0) loc.Y = 0;
        //            if (loc.Y + canvas1.ActualHeight > ActualHeight) loc.Y = ActualHeight - canvas1.ActualHeight;
        //        }
        //        // Location(postcheck)
        //        canvas1.Margin = new Thickness(loc.X, loc.Y, canvas1.Margin.Right + offset.X, canvas1.Margin.Bottom + offset.Y);
        //        // "This mouse position. " saved as "Previous mouse position. "
        //        myPointPrev = myPointThis;
        //    }
        //}
        //private void canvas1_MouseUp(object sender, MouseButtonEventArgs e)
        //{
        //    isMoving = false;
        //}
        #endregion

        #region Pan tool #1(has backup above)
        bool panning;
        Point prevPoint;
        TranslateTransform transFinal = new TranslateTransform();
        TranslateTransform transInitial = new TranslateTransform();

        private void canvas1_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Focus();
            panning = e.LeftButton == MouseButtonState.Pressed;
            if (panning)
            {
                prevPoint = e.GetPosition(this);
            }
        }
        private void canvas1_MouseMove(object sender, MouseEventArgs e)
        {
            if (panning)
            {
                Point thisPoint = e.GetPosition(this);
                Vector offset = new Vector(thisPoint.X - prevPoint.X, thisPoint.Y - prevPoint.Y);
                transInitial.X += offset.X;
                transInitial.Y += offset.Y;

                //if (canvas1.ActualWidth >= ActualWidth && canvas1.ActualHeight >= ActualHeight)
                //{
                //    if (transInitial.X > 0) transInitial.X = 0;
                //    if (transInitial.Y > 0) transInitial.Y = 0;
                //    if (transInitial.X + canvas1.ActualWidth < ActualWidth)
                //        transInitial.X = ActualWidth - canvas1.ActualWidth;
                //    if (transInitial.Y + canvas1.ActualHeight < ActualHeight)
                //        transInitial.Y = ActualHeight - canvas1.ActualHeight;
                //}
                //else if (canvas1.ActualHeight >= ActualHeight)
                //{
                //    if (transInitial.X < 0) transInitial.X = 0;
                //    if (transInitial.Y > 0) transInitial.Y = 0;
                //    if (transInitial.X + canvas1.ActualWidth > ActualWidth)
                //        transInitial.X = ActualWidth - canvas1.ActualWidth;
                //    if (transInitial.Y + canvas1.ActualHeight < ActualHeight)
                //        transInitial.Y = ActualHeight - canvas1.ActualHeight;
                //}
                //else if (canvas1.ActualWidth >= ActualWidth)
                //{
                //    if (transInitial.X > 0) transInitial.X = 0;
                //    if (transInitial.Y < 0) transInitial.Y = 0;
                //    if (transInitial.X + canvas1.ActualWidth < ActualWidth)
                //        transInitial.X = ActualWidth - canvas1.ActualWidth;
                //    if (transInitial.Y + canvas1.ActualHeight > ActualHeight)
                //        transInitial.Y = ActualHeight - canvas1.ActualHeight;
                //}
                //else
                //{
                //    if (transInitial.X < 0) transInitial.X = 0;
                //    if (transInitial.Y < 0) transInitial.Y = 0;
                //    if (transInitial.X + canvas1.ActualWidth > ActualWidth)
                //        transInitial.X = ActualWidth - canvas1.ActualWidth;
                //    if (transInitial.Y + canvas1.ActualHeight > ActualHeight)
                //        transInitial.Y = ActualHeight - canvas1.ActualHeight;
                //}
                transFinal.X = transInitial.X;
                transFinal.Y = transInitial.Y;
                prevPoint = thisPoint;
            }
        }
        private void canvas1_MouseUp(object sender, MouseButtonEventArgs e)
        {
            panning = false;
        }
        private void canvas1_MouseLeave(object sender, MouseEventArgs e)
        {
            if (panning)
                panning = false;
        }
        #endregion

        #region StarProduction toggle view
        private void canvas1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Space && StarProdToggleAllowed)
            {
                ((Star)canvas1.Children[starIndex]).IsShowingProduction = false;
                starIndex = -1;
            }
        }
        private void canvas1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Space && StarProdToggleAllowed)
            {
                lastStarIndex = starIndex;
                Point mousePoint = Mouse.GetPosition(canvas1), ctrlPoint;
                double distance, lastNearest = double.MaxValue;

                foreach (Star star in starArray) // canvas1.Children
                {
                    ctrlPoint = new Point(Canvas.GetLeft(star), Canvas.GetTop(star));
                    distance = Math.Sqrt(Math.Pow((mousePoint.X - ctrlPoint.X), 2) + Math.Pow((mousePoint.Y - ctrlPoint.Y), 2));
                    if (distance < lastNearest)
                    {
                        lastNearest = distance;
                        starIndex = canvas1.Children.IndexOf(star);
                    }
                }
                if (lastStarIndex == -1)
                {
                    ((Star)canvas1.Children[starIndex]).IsShowingProduction = true;
                }
                else if (lastStarIndex != starIndex)
                {
                    ((Star)canvas1.Children[lastStarIndex]).IsShowingProduction = false;
                    ((Star)canvas1.Children[starIndex]).IsShowingProduction = true;
                }
            }
        } 
        #endregion

        /// <summary>
        /// For stealing focus. It is relayed from canvas1 since it doesn't support Focus().
        /// </summary>
        private void UserControl_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Focus();
        }
        
        ScaleTransform scaleTransform = new ScaleTransform();
        /// <summary>
        /// Zoom
        /// </summary>
        private void canvas1_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            int notches = e.Delta / 120;
            double factor = notches * 0.1;

            //Point centerStarMap = new Point(ActualWidth/2, ActualHeight/2);
            //Point scaleCenterCanvas1 = canvas1.PointFromScreen(PointToScreen(centerStarMap));

            scaleTransform.CenterX = canvas1.Width / 2;
            scaleTransform.CenterY = canvas1.Height / 2;
            scaleTransform.ScaleX += factor;
            scaleTransform.ScaleY += factor;
        }

        /// <summary>
        /// Quit to desktop menu choice.
        /// </summary>
        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }
        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void New_game_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.MainWindow.Content = new StartGameMenu();
        }
        #endregion

        #region Properties
        public static bool StarProdToggleAllowed
        {
            get { return starProdToggleAllowed; }
            set { starProdToggleAllowed = value; }
        } 
        #endregion

        #region Fields
        int lastStarIndex, starIndex = -1;
        TransformGroup transformGroup;
        static bool starProdToggleAllowed = true;

        RemoteGame.Game _game;
        TcpChannel _tcpChannel1;

        public TcpChannel TcpChannel1
        {
            get { return _tcpChannel1; }
            set { _tcpChannel1 = value; }
        }

        public RemoteGame.Game Game
        {
            get { return _game; }
            set { _game = value; }
        }
        #endregion

        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            Disconnect();
        }
    }
}
